::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::
Introduction
The first adventure games were text only. Surely you remember
|
West of House You are in an open field west of a big white house, with a boarded front door. There is a small mailbox here. >Open mailbox Opening the small mailbox reveals a leaflet. >Read leaflet (Taken) "WELCOME TO ZORK! |
Later on, graphics were added to the text based adventure game. These graphics were not an integral part of the game, but merely served as illustrations. Apple's Mystery House is credited with being the first adventure game to include graphics. Gameplay still relied heavily upon the written descriptions of locations, objects and events.

One of the earliest games to shift away from the written description to more visual clues was Sierra's King's Quest. Rather than reading about the well, the well was actually visible. Once the object was taken, that object was removed from the graphic display. A textbox was still required for user input, as the player was still forced to type
|
>Take apple Okay. You place the apple in your inventory. |
Hoping to decrease player frustration resulting from both tedious typing and non-recognized user entries, game designers opted for total mouse driven play. Typically, two comboxes were used. The first contained an array of verbs, the second an array of nouns. Only options available to that location and inventory list were displayed. Still, the verb - noun combination was sometimes klutzy and always distracting. Many players resented the 'walkthrough' ease of play delivered by the dropdown lists. These games were not well received.
Fortunately, technology favored the gaming industry. Low-resolution graphics gave way to Hi-resolution graphics and sprite animation allowed true Point and Click games. Text messaging, especially in the form of either character or narrative dialog, took a back seat to the mouse cursor against the graphic background. Rather than
|
>Walk west A steep mountain range blocks your way. You cannot move west. |
the user sees the granite border and the mouse cursor fails to give the familiar west arrow appearance.
When interacting with objects, what used to be
|
>Open chest You find 23 gold coins and one healing potion |
is now a series of pictures showing a closed treasure chest, an open filled treasure chest, and an open empty treasure chest. The inventory list now includes the 23 gold pieces and the healing potion.
Point and Click in Liberty BASIC
Can you make a 'Point and Click' game in Liberty BASIC? Sure you can. All you need are the graphics, the sprites, the cursors, a scripting and parsing routine, and a bit of imagination.
Each location is assigned a background graphic. Graphics are both memory and disk intensive. One way to reduce memory and file size is to use .gif files rather than .bmp. Liberty BASIC has no native command to load .gif files, but non-bitmap graphics are easily loaded into LB programs using Alyce Watson's jpeg.dll. Each location gif is given the name of the corresponding room or cell number (e.g., cell001.gif, cell002.gif). The sprites are also in .gif format and also named by assigned number (e.g., obj0001.gif, obj0002.gif).
The actual 'Point and Click' is accomplished with the when mouseMove command and the spritescollides command. A simple 2 pixel (one pixel for the sprite, the other for the mask) is used to travel with the cursor. It is this simple 2 pixel sprite (obj0000) that initiates the collision list.
#main.gb1, "When mouseMove [FindObjects]"
In the [FindObjects] block of code, look for a sprite collision.
CurX = MouseX
CurY = MouseY
#main.gb1, "Spritexy obj0000 ";CurX;" ";CurY
#main.gb1, "Drawsprites"
#main.gb1, "Spritecollides obj0000 CollisionList$"
The Custom Cursor
When no sprite collision is taking place, the cursor remains the usual arrow. When a collision is taking place, the program informs the user than the object is 'clickable' by changing to a grabbing hand cursor.
If Instr(CollisionList$, "obj") > 0 Then
CurHandle = LoadCursor(32649)
Call ObjectDesc CollisionList$
OldList$ = CollisionList$
#main.gb1, "When leftButtonUp [SelectObject]"
End If
If the player then left clicks the mouse, the object is selected. Otherwise, as the player moves away from the sprite and collision is no longer detected, the cursor returns to the normal arrow shape.
Movements out of the current location to a new location are also visually depicted using a custom cursor and sprites. Four egress sprites are loaded, one at each of the four edges. If the cursor & obj0000 collides with an egress sprite, the cursor changes to the appropriate direction arrow.
Invisible Sprites
Even invisible sprites initiate collisions. This allows the egress sprites to remain invisible to the player. The egress sprites must be physically moved from the available graphic box space if collision is not desired. This would be the case when the player cannot move in a particular direction, or if an object has been added to the player's inventory. Moving the sprite out of the graphicbox area is accomplished with negative x or y coordinates.
Adding to the Inventory
To conserve file space and memory, the same masked .gif pic is used for both sprite and inventory. By drawing the .gif pic using the midheight for y, the mask is not visible to the viewer. Not all sprite objects can be taken. Some are there for descriptive purposes only.
Location Information
A sequential text file is used to store data for each of the locations. As the file is read, the information is stored in the array cellInfo$(). Information is extracted using the Word$ function with the pipe (|) as the deliminator. The information stored in each line entry is
1:SHORT DESCRIPTION
2:FIRST VISIT TO ROOM
3:RETURN VISIT TO ROOM
4:AFTER SPECIAL EVENT
5:EGRESS '0 2 0 0
6:OBJECT 1 '(1 230 250)
7:OBJECT 2 '(2 280 250)
8:OBJECT 3 '(3 220 121)
9:OBJECT 4 '(0 0 0)
The first 3 elements are just descriptions. The 4th element can be called later in the game. An example would be a room containing a burning fireplace, but later that fire was doused. Number 5, the egress information, tells which room or cell is entered by that exiting in that direction. The order of egresses are N, E, S, W. In the above example, the north, south and west exits are blocked. Moving east places the player in cell #2. The object information contains the number of the sprite, the x coordinate of the sprite, and the 6 coordinate of the sprite. This demo allows a maximum of four sprite objects per room.
Object Information
The second sequential text file contains the information for each sprite object. It is this file that contains all the information necessary for game play. As with the location information, information is first read from the text file using Line Input. Later, the Word$() function with the pipe (|) deliminator is used to extract specific information about that object. The information includes
1:Objn-Short Description
2:Detailed Description
3:Take Description
4:InvBox
5:InvCoords
6:UseRoom
7:NumberValidResponsesNonUseRoom
8:Response1
9:Response2
10:Response3
11:SpriteRequiredInUseRoom 0=No,1=Yes
12:NumberValidResponses
13:Response1
14:Response2
15:Response3
16:InventoryItemRequired 0=No,1=Yes
17:NumberValidResponses
18:Response1
19:Response2
20:Response3
21:ToBeDetermined 0=No,1=Yes
22:NumberValidResponses
23:Response1
24:Response2
25:Response3
26:USEITEMNumberOfCommandsToFollow
27+:The sequence of commands
Elements 1 - 3 are descriptive. Elements 4 and 5 are necessary to tell which inventory graphicbox to draw the .gif and the upper left x and y coordinates necessary to hide the mask. Element 6 stores the room in which the object can be used. Element 7 tells how many (3 maximum) responses can be randomly called if the player attempts to use that item in any other room. Elements 8, 9 and 10 hold those responses. It might be necessary for another object to be available in that room for this object to be used. The number of that sprite object is held in element 11 (0 = no sprite object required). Again, if the sprite object is not available in the use room, a number of responses might be given (elements 12 -15). It might be necessary to have a second item in inventory before an object can be used. That second item is stored in element 16 and the available responses when that second item is lacking being stored in elements 17 -20. Because this demo was meant to be built upon, a third block of similar information was added without any particular assignment. All objects have these 25 items separated by the pipe deliminator. If all conditions are met, (i.e., the right room and any other required object available), the object can be used. A number of commands are then executed. The number of commands is stored in element 26. A loop is set up to extract and execute commands 27 forth.
Parsing and Scripting
Execution of the commands are accomplished using Select Case. Each command is followed by any necessary arguments, separated by a hyphen (-) deliminator.
For i = 1 to nCommands
Parse$ = Word$(ObjectInfo$(nObj), 26 + i, "|")
Command = Val(Word$(Parse$, 1, ":"))
Command$ = Word$(Parse$, 2, ":")
Select Case Command 'The Execution of the Scripted Commands
Case 1 'Print
handle$ = Word$(Command$, 1, "-")
Print #handle$, Word$(Command$, 2, "-")
Case 2 'Clear Inv Screen
handle$ = "#main.inv";Val(Command$)
Print #handle$, "Getbmp InvObj 0 0 80 80"
Print #handle$, "Cls; Fill Buttonface; Flush"
Case 3 'Redraw Inventory Item
handle$ = "#main.inv";Val(Command$)
Print #handle$, "Drawbmp InvObj 0 0; Flush"
Case 4 'Add / Remove a Visible Object
VisObj = Val(Word$(Command$, 1))
VisState = Val(Word$(Command$, 2))
VisibleObject(VisObj) = VisState
SpriteObject$ = "obj";ZeroFiller$(VisObj, 4)
x = Val(Word$(Command$, 3))
y = Val(Word$(Command$, 4))
#main.gb1, "Spritexy ";SpriteObject$;" ";x;" ";y
#main.gb1, "Drawsprites"
Case 5 'DelayTime
Call Sleep Val(Command$)
End Select
Next i
By parsing carefully constructed scripted text, the adventure game with 1000 locations uses the same program as this demo holding just 3 locations. All that's needed are more entries to the cellInfo.txt file and the objectInfo.txt file. The two commands, Word$() and Select Case are used extensively throughout this demo. Feel free to adapt the code to meet your needs.
More Resources
Where can you learn more about loading non bitmap pic files with the jpeg.dll? [Alyce's Restaurant]
Where can you learn more about sprites? The Sprite Byte Series by Alyce Watson (LB Newsletters 119 - Present)
Where can you learn more about loading custom cursors? Custom Cursors With LoadCursorFromFile (LB Newsletter #135)
Where can you learn more about parsing and scripted language? Scripting Language Tutorial (LB Newsletter #98), Comal Dll: MS Agent and Liberty BASIC (LB Newsletter #126), Chat Challenge (LB Newsletter #133)
DEMO
The file PointClickAdvJLT.bas, with associated image and text files, is included in the zipped archive of this newsletter.
::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::